# IT-Planet_If_else_Duvakin

Не успел сделать всю коллекцию и varibels, но тела зпросов уже заполнены и готовы

Веб приложение по адресу:
http://localhost:5000/

## Компания «История Погоды»

## Условия

Участник предоставляет Организатору разрешение на использование, модификацию, публикацию проекта и дальнейшее
распространение, включая право на внесение изменений, дополнений, предисловий, комментариев и любых других переработок.
Участник гарантирует, что проект не нарушает действующее законодательство, не содержит информации, дискредитирующей лиц
или продукты, не вызывает судебных исков или претензий, не нарушает прав и интересов третьих лиц, соответствует
общественным интересам, принципам гуманности и морали. Участник подтверждает, что все используемые в проекте материалы и
данные являются его собственностью или использованы с разрешения правообладателей, что не ограничивает использование
проекта Организатором в полном объеме.
Участник подтверждает, что передача исключительных прав на проект, созданный в рамках конкурса, не нарушает права
третьих лиц и что все материалы проекта могут быть использованы Организатором без каких-либо ограничений.

## Описание системы

Система представляет собой сервис API, разработанный на языке Python с использованием фреймворка Flask, СУБД PostgreSQL
и платформы, предназначенной для разработки, развёртывания и запуска приложений в контейнерах - Docker, который
предназначен
для сбора, хранения и анализа метеорологических данных. А также веб приложение для просмотра информации о методах и
использовании интерактивной карты. Система включает в себя следующие компоненты:

* Flask: основная часть системы, предоставляющая HTTP-интерфейс для взаимодействия с метеорологической информацией.
  Flask обрабатывает запросы от клиентов и возвращает соответствующие данные.

* PostgreSQL: реляционная база данных, используемая для хранения всех метеорологических данных, а также информации о
  пользователях и других сущностях системы.

* Docker: используется для контейнеризации приложения, что облегчает его развертывание и масштабирование.

Структура проекта включает в себя различные файлы и директории, такие как файлы Flask приложения, модели данных, скрипты
для генерации тестовых данных, а также файлы конфигурации Docker и зависимости в файле requirements.txt.

Цель системы состоит в том, чтобы предоставить удобный и надежный способ сбора, хранения и доступа к
метеорологической информации для дальнейшего анализа и использования.

## Запуск системы

Перед запуском системы убедитесь, что на вашем компьютере установлены Docker и Docker Compose. Если они не установлены,
следуйте инструкциям на [официальном сайте Docker](https://www.docker.com/) для вашей операционной системы.

Также обратите внимание, что для запуска потребуется подключение к интернету. Для работы приложения будет скачан образ
СУБД PostgreSQL и необходимые зависимости (библиотеки).

Для работы приложения необходимо задать ключ шифрования, для этого нужно создать файл ".env" с определенной внутри
переменной "secure_key". Это не является обязательным условием т.к. в случае отсутствия переменной окружения система
сгенерирует ключ случайным образом. Пример [.env](.env) файла.

![img.png](images/img3.png)

Для запуска система откройте терминал в папке [WeatherService](WeatherService) и запустите одну из команд:  
`docker compose up` или `docker-compose up`  
Начнется запуск системы. Обратите внимание, что даже если Docker сообщает о запуске контейнеров, для запуска программы
внутри контейнеров может потребоваться дополнительное время, до 20 секунд.

После запуска системы, методы API будут доступны по адресу localhost:5000 (при условии, что конфигурация не была
изменена), а база
данных по адресу localhost:5432 (при условии, что конфигурация не была изменена).

Обратите внимание, что для работы система использует порты 5432 и 5000. Если во время запуска данные порты будут заняты
другими программами, то будет вызвано исключение. Для изменения портов, по которым может быть доступен API сервис и база
данных, измените первую часть параметра "ports" в файле [docker-compose.yml](WeatherService%2Fdocker-compose.yml) у базы
данных и приложения.

### Для базы данных:

![img.png](images/img.png)

### Для API:

![img_1.png](images/img_1.png)

### Заполнение тестовыми данными

Для удобства тестирования при первом запуске контейнера происходит заполнение базы тестовыми данными. Создается новый
пользователь для возможности быстрой авторизации.

Данные авторизации тестового пользователя:

```json
{
  "email": "test@user.ru",
  "password": "test_password"
}
```

Автоматическое заполнение базы можно отключить, убрав команду `&& python3 init_test_data.py` из
файла [docker-compose.yml](WeatherService%2Fdocker-compose.yml).

![img.png](images/img4.png)

### Готовые тесты Postman

Для автоматизации тестирования можно воспользоваться подготовленной коллекцией запросов
Postman v2.1: [ItPlanet.postman_collection.json](postman_collection%2FItPlanet.postman_collection.json).
Запросы написаны для тестовых данных, которые добавляются в базу данных автоматически при первом запуске контейнера.

# Веб приложение

Для удобного просмотра информации о методах было разработано веб-приложение.

![img.png](images/img22.png)
![img.png](images/img23.png)

На главной странице расположен список всех методов (старых и новых), а также кнопка для перехода на страницу с картой.

На странице с картой расположена сама карта и поле для ввода координат.

![img.png](images/img24.png)

После нажатия на кнопку "показать область" на карте будет отрисован заданный отрезок, также система првоерит наличие
региона с такими координатами в базе данных и в случае обнаружения выведет информацию о регионе.

![img.png](images/img25.png)

При открытии метода на главной странице, будет показана основная информация о методе, а также представлен пример
запроса.

![img.png](images/img26.png)

# Методы

# OSM Методы

## Получение информации о регионе

Метод: **GET**

Путь: **/region/{regionId}**

#### Запрос

Параметры пути:

- **regionId** (обязательно): Идентификатор региона (тип: long).

Тело запроса:

- Пустое.

#### Ответ

В случае успешного выполнения возвращает JSON-объект с полями:

- **id**: Идентификатор региона (тип: long).
- **regionType**: Массив идентификаторов типа региона (тип: [long]).
- **accountId**: Аккаунт, внесший данные о регионе (тип: long).
- **name**: Название региона (тип: string).
- **parentRegion**: Название родительского региона (тип: string).
- **latitude**: Координаты широты (тип: double).
- **longitude**: Координаты долготы (тип: double).
- **osmData**: Объект с данными из OpenStreetMap:
    - **mapLink**: Ссылка на карту региона в OSM (тип: string).
    - **boundingBox**: Границы региона (тип: [double, double, double, double]).
    - **pointsOfInterest**: Массив точек интереса, каждая из которых включает:
        - **name**: Название точки интереса (тип: string).
        - **type**: Тип точки интереса (тип: string).
        - **latitude**: Широта (тип: double).
        - **longitude**: Долгота (тип: double).
        - **latitude_2**: Широта (тип: double).
        - **longitude_2**: Долгота (тип: double).

#### Статусы

- **200**: Запрос успешно выполнен.
- **400**:
    - Если `regionId` отсутствует или имеет некорректное значение (нулевой или отрицательный).
- **401**: Неверные авторизационные данные.
- **404**: Регион с таким `regionId` не найден.

Пример запроса:

```http
GET /region/123
```

Пример ответа:

```json
{
  "id": 123,
  "regionType": [
    1,
    2
  ],
  "accountId": 456,
  "name": "Moscow",
  "parentRegion": "Russia",
  "latitude": 55.7558,
  "longitude": 37.6176,
  "latitude_2": 55.7558,
  "longitude_2": 37.6176,
  "osmData": {
    "mapLink": "https://www.openstreetmap.org/search?query=Moscow",
    "boundingBox": [
      [
        55.85222,
        37.61556
      ],
      [
        55.85222,
        37.71556
      ],
      [
        55.75222,
        37.71556
      ],
      [
        55.75222,
        37.61556
      ]
    ],
    "pointsOfInterest": [
      {
        "name": "Red Square",
        "type": "historical",
        "latitude": 55.7539,
        "longitude": 37.6208
      }
    ]
  }
}
```

## Добавление региона

Метод: **POST**

Путь: **/region**

### Запрос

Принимает JSON-объект с полями:

- **name** (обязательно): Название региона.
- **parentRegion** (необязательно): Название родительского региона, может быть Null.
- **latitude** (обязательно): Координаты широты.
- **longitude** (обязательно): Координаты долготы.
- **osmData** (необязательно): Данные для интеграции с OpenStreetMap.
    - **includePOI**: Указывает, следует ли включать точки интереса из OSM. True для включения, False или отсутствует
      для игнорирования.

### Статусы

- 201: Запрос успешно выполнен.
- 400: Ошибка в полученных данных. Если поле name отсутствует, пустое или состоит только из пробелов. Если поля latitude
  или longitude отсутствуют.
- 401: Неверные авторизационные данные.
- 409: Регион с такими latitude и longitude уже существует.

### Пример запроса

```json
{
  "name": "Example Region",
  "parentRegion": "Parent Region",
  "latitude": 55.7558,
  "longitude": 37.6176,
  "osmData": {
    "includePOI": true
  }
}
```

### Пример ответа

```json
{
  "id": 1,
  "name": "Example Region",
  "parentRegion": "Parent Region",
  "latitude": 55.7558,
  "longitude": 37.6176,
  "latitude_2": 55.8558,
  "longitude_2": 37.7176,
  "osmData": {
    "mapLink": "http://osm.org/link-to-region",
    "boundingBox": [
      [
        55.85222,
        37.61556
      ],
      [
        55.85222,
        37.71556
      ],
      [
        55.75222,
        37.71556
      ],
      [
        55.75222,
        37.61556
      ]
    ],
    "pointsOfInterest": [
      {
        "name": "Example POI",
        "type": "landmark",
        "latitude": 55.7559,
        "longitude": 37.6175
      }
    ]
  }
}
```

## Изменение региона

Метод: **PUT**

Путь: **/region/{regionId}**

### Запрос

Принимает JSON-объект с полями:

- **name** (обязательно): Новое название региона.
- **parentRegion** (необязательно): Новое название родительского региона, может быть `Null`.
- **latitude** (обязательно): Новые координаты широты.
- **longitude** (обязательно): Новые координаты долготы.
- **osmData** (необязательно): Данные для запроса обновления информации из OpenStreetMap.
    - **updatePOI**: Указывает на необходимость обновления точек интереса из OSM. `True` для обновления, `False` или
      отсутствует для игнорирования.

### Пример запроса

```json
{
  "name": "New Region Name",
  "parentRegion": "Parent Region",
  "latitude": 34.0522,
  "longitude": -118.2437,
  "osmData": {
    "updatePOI": true
  }
}
```

### Пример ответа:

```json
{
  "id": 123,
  "name": "New Region Name",
  "parentRegion": "Parent Region",
  "latitude": 34.0522,
  "longitude": -118.2437,
  "latitude_2": 55.85222,
  "longitude_2": 37.71556,
  "osmData": {
    "mapLink": "http://osm.org/link-to-region",
    "boundingBox": [
      [
        55.85222,
        37.61556
      ],
      [
        55.85222,
        37.71556
      ],
      [
        55.75222,
        37.71556
      ],
      [
        55.75222,
        37.61556
      ]
    ],
    "pointsOfInterest": [
      {
        "name": "Point of Interest",
        "type": "Park",
        "latitude": 34.0523,
        "longitude": -118.2438
      }
    ]
  }
}
```

## Получение информации о погоде в регионе

Метод: **GET**

Путь: **/region/weather/{regionId}**

### Запрос

Тело запроса: пустое

### Пример запроса

```http
GET /region/weather/123
```

## Пример ответа

```json
{
  "id": 123,
  "regionName": "Region Name",
  "temperature": 22.5,
  "humidity": 60.0,
  "windSpeed": 5.0,
  "weatherCondition": "CLEAR",
  "precipitationAmount": 0.0,
  "measurementDateTime": "2024-05-24T14:30:00Z",
  "weatherForecast": [
    {
      "forecastId": 456,
      "dateTime": "2024-05-25T14:30:00Z",
      "temperature": 24.0,
      "weatherCondition": "CLOUDY",
      "precipitationAmount": 0.5,
      "windSpeed": 4.0
    }
  ],
  "osmLink": "http://osm.org/link-to-region"
}
```

# Остальные методы

## Создание пользователя

Метод: **POST**

Путь: **/registration**

#### Запрос

Принимает JSON-объект с полями:

- **firstName** (обязательно): Имя пользователя.
- **lastName** (обязательно): Фамилия пользователя.
- **email** (обязательно): Адрес электронной почты пользователя.
- **password** (обязательно): Пароль от аккаунта пользователя.

#### Ответ

В случае успешного создания пользователя возвращает JSON-объект с полями:

- **id**: Идентификатор аккаунта пользователя.
- **firstName**: Имя пользователя.
- **lastName**: Фамилия пользователя.
- **email**: Адрес электронной почты.

#### Статусы

- **201**: Запрос успешно выполнен.
- **400**:
    - Если отсутствуют обязательные поля в теле запроса.
    - Если поля `firstName`, `lastName`, `email` или `password` пусты или состоят только из пробелов.
    - Если адрес электронной почты некорректен.
- **403**: Запрос от авторизованного аккаунта.
- **409**: Аккаунт с таким адресом электронной почты уже существует.

Пример запроса:

```json
{
  "firstName": "John",
  "lastName": "Doe",
  "email": "john.doe@example.com",
  "password": "password123"
}
```

Пример ответа:

```json
{
  "id": 123,
  "firstName": "John",
  "lastName": "Doe",
  "email": "john.doe@example.com"
}
```

## Аутентификация пользователя

Метод: **POST**

Путь: **/login**

#### Запрос

Принимает JSON-объект с полями:

- **email** (обязательно): Адрес электронной почты пользователя.
- **password** (обязательно): Пароль от аккаунта пользователя.

#### Ответ

В случае успешной аутентификации возвращает JSON-объект с полем:

- **id**: Идентификатор аккаунта пользователя.

#### Статусы

- **200**: Запрос успешно выполнен.
- **400**: Отсутствуют обязательные поля `email` или `password` в теле запроса.
- **401**: Неверный email или пароль.

Пример запроса:

```json
{
  "email": "john.doe@example.com",
  "password": "password123"
}
```

Пример ответа:

```json
{
  "id": 123
}
```

## Аккаунт пользователя

Метод: **GET**

Путь: **/accounts/{accountId}**

#### Запрос

Не принимает тело запроса.

#### Ответ

Возвращает JSON-объект с полями:

- **id**: Идентификатор аккаунта пользователя.
- **firstName**: Имя пользователя.
- **lastName**: Фамилия пользователя.
- **email**: Адрес электронной почты.

#### Статусы

- **200**: Запрос успешно выполнен.
- **400**: Некорректный идентификатор `accountId`.
- **401**: Неверные авторизационные данные.
- **404**: Аккаунт с указанным `accountId` не найден.

Пример запроса:

```http
GET /accounts/123 HTTP/1.1
```

Пример ответа:

```json
{
  "id": 123,
  "firstName": "John",
  "lastName": "Doe",
  "email": "john.doe@example.com"
}
```

## Поиск аккаунта

Метод: **GET**

Путь: **/accounts/search**

#### Запрос

Принимает параметры запроса:

- **firstName** (опционально): Имя пользователя, по которому будет производиться поиск. Может использоваться только
  часть имени без учета регистра. Если параметр отсутствует, не участвует в фильтрации.
- **lastName** (опционально): Фамилия пользователя, по которой будет производиться поиск. Может использоваться только
  часть фамилии без учета регистра. Если параметр отсутствует, не участвует в фильтрации.
- **email** (опционально): Адрес электронной почты пользователя, по которому будет производиться поиск. Может
  использоваться только часть адреса электронной почты без учета регистра. Если параметр отсутствует, не участвует в
  фильтрации.
- **from** (опционально): Количество элементов, которое необходимо пропустить для формирования страницы с результатами (
  по умолчанию 0).
- **size** (опционально): Количество элементов на странице (по умолчанию 10).

#### Ответ

Возвращает массив JSON-объектов с полями:

- **id**: Идентификатор аккаунта пользователя.
- **firstName**: Имя пользователя.
- **lastName**: Фамилия пользователя.
- **email**: Адрес электронной почты.

Результаты поиска сортируются по идентификатору аккаунта пользователя от наименьшего к наибольшему.

#### Статусы

- **200**: Запрос успешно выполнен.
- **400**: Ошибка в параметрах запроса (`from < 0` или `size <= 0`).
- **401**: Неверные авторизационные данные.

Пример запроса:

```http
GET /accounts/search?firstName=John&lastName=Doe&email=john.doe@example.com&from=0&size=10 HTTP/1.1
```

Пример ответа:

```json
[
  {
    "id": 123,
    "firstName": "John",
    "lastName": "Doe",
    "email": "john.doe@example.com"
  },
  {
    "id": 456,
    "firstName": "John",
    "lastName": "Smith",
    "email": "john.smith@example.com"
  }
]
```

## Изменение аккаунта

Метод: **PUT**

Путь: **/accounts/{accountId}**

#### Запрос

Принимает JSON-объект с полями:

- **firstName** (обязательно): Новое имя пользователя.
- **lastName** (обязательно): Новая фамилия пользователя.
- **email** (обязательно): Новый адрес электронной почты пользователя.
- **password** (обязательно): Пароль от аккаунта пользователя.

#### Ответ

Возвращает JSON-объект с полями:

- **id**: Идентификатор аккаунта пользователя.
- **firstName**: Новое имя пользователя.
- **lastName**: Новая фамилия пользователя.
- **email**: Новый адрес электронной почты.

#### Статусы

- **200**: Запрос успешно выполнен.
- **400**: Отсутствуют обязательные поля (`firstName`, `lastName`, `email` или `password`) или они пусты. Неверный
  формат email.
- **401**: Неверные авторизационные данные.
- **403**: Обновление не своего аккаунта.
- **404**: Аккаунт не найден.
- **409**: Аккаунт с таким email уже существует.

Пример запроса:

```http
PUT /accounts/123 HTTP/1.1
Content-Type: application/json

{
  "firstName": "John",
  "lastName": "Doe",
  "email": "john.doe@example.com",
  "password": "newpassword123"
}
```

Пример ответа:

```json
{
  "id": 123,
  "firstName": "John",
  "lastName": "Doe",
  "email": "john.doe@example.com"
}
```

## Удаление аккаунта

Метод: **DELETE**

Путь: **/accounts/{accountId}**

#### Запрос

Принимает пустое тело запроса.

#### Ответ

Возвращает пустое тело ответа.

#### Статусы

- **200**: Запрос успешно выполнен.
- **400**: Некорректный идентификатор аккаунта (`accountId` равен `null` или меньше или равен 0).
- **401**: Неверные авторизационные данные.
- **403**: Удаление не своего аккаунта.
- **404**: Аккаунт с указанным `accountId` не найден.

Пример запроса:

```http
DELETE /accounts/123 HTTP/1.1
```

Пример ответа:

```http
HTTP/1.1 200 OK
Content-Length: 0
```

## Получение информации о регионе

Метод: **GET**

Путь: **/region/{regionId}**

#### Запрос

Принимает пустое тело запроса.

#### Ответ

Возвращает информацию о регионе в формате JSON:

- **id**: Идентификатор региона.
- **regionType**: Идентификатор типа региона.
- **accountld**: Идентификатор аккаунта, внесшего данные о регионе.
- **name**: Название региона.
- **parentRegion**: Название родительского региона.
- **latitude**: Координаты широты.
- **longitude**: Координаты долготы.

#### Статусы

- **200**: Запрос успешно выполнен.
- **400**: Некорректный идентификатор региона (`regionId` равен `null` или меньше или равен 0).
- **401**: Неверные авторизационные данные.
- **404**: Регион с указанным `regionId` не найден.

Пример запроса:

```http
GET /region/123 HTTP/1.1
```

Пример ответа:

```json
{
  "id": 123,
  "regionType": 456,
  "accountld": 789,
  "name": "Название региона",
  "parentRegion": "Название родительского региона",
  "latitude": 55.123456,
  "longitude": 37.654321
}
```

## Создание региона

Метод: **POST**

Путь: **/region**

#### Запрос

Принимает JSON-объект с полями:

- **name** (обязательно): Название региона.
- **latitude** (обязательно): Координаты широты.
- **longitude** (обязательно): Координаты долготы.
- **regionType** (опционально): Идентификатор типа региона.
- **parentRegion** (опционально): Название родительского региона.

#### Ответ

Возвращает информацию о созданном регионе в формате JSON:

- **id**: Идентификатор созданного региона.
- **name**: Название региона.
- **parentRegion**: Название родительского региона (если указано).
- **regionType**: Идентификатор типа региона (если указан).
- **latitude**: Координаты широты.
- **longitude**: Координаты долготы.

#### Статусы

- **201**: Запрос успешно выполнен и регион создан.
- **400**: Отсутствуют обязательные поля в теле запроса (`name`, `latitude`, `longitude`).
- **401**: Неверные авторизационные данные.
- **404**: Тип региона или родительский регион не найдены.
- **409**: Регион с указанными координатами уже существует.

Пример запроса:

```http
POST /region HTTP/1.1
Content-Type: application/json

{
  "name": "Название региона",
  "latitude": 55.123456,
  "longitude": 37.654321
}
```

Пример ответа:

```json
{
  "id": 123,
  "name": "Название региона",
  "parentRegion": "Название родительского региона",
  "regionType": 456,
  "latitude": 55.123456,
  "longitude": 37.654321
}
```

## Изменение региона

Метод: **PUT**

Путь: **/region/{regionld}**

#### Запрос

Принимает JSON-объект с полями:

- **name** (обязательно): Новое название региона.
- **latitude** (обязательно): Новые координаты широты.
- **longitude** (обязательно): Новые координаты долготы.
- **regionType** (опционально): Новый идентификатор типа региона.
- **parentRegion** (опционально): Новое название родительского региона.

#### Ответ

Возвращает информацию о измененном регионе в формате JSON:

- **id**: Идентификатор измененного региона.
- **name**: Новое название региона.
- **parentRegion**: Новое название родительского региона (если указано).
- **latitude**: Новые координаты широты.
- **longitude**: Новые координаты долготы.

#### Статусы

- **200**: Запрос успешно выполнен и регион изменен.
- **400**: Отсутствуют обязательные поля в теле запроса (`name`, `latitude`, `longitude`).
- **401**: Неверные авторизационные данные.
- **404**: Регион с указанным идентификатором не найден.
- **409**: Регион с указанными координатами уже существует.

Пример запроса:

```http
PUT /region/{123} HTTP/1.1
Content-Type: application/json

{
  "name": "Новое название региона",
  "latitude": 55.123456,
  "longitude": 37.654321
}
```

Пример ответа:

```json
{
  "id": 123,
  "name": "Новое название региона",
  "parentRegion": "Новое название родительского региона",
  "latitude": 55.123456,
  "longitude": 37.654321
}
```

## Удаление региона

Метод: **DELETE**

Путь: **/region/{regionld}**

#### Запрос

Не принимает тело запроса.

#### Ответ

Не возвращает тело ответа.

#### Статусы

- **200**: Запрос успешно выполнен и регион удален.
- **400**: Регион является родительским для другого региона.
- **401**: Неверные авторизационные данные.
- **404**: Регион с указанным идентификатором не найден.

Пример запроса:

```http
DELETE /region/{123} HTTP/1.1
Authorization: Bearer {token}
```

Пример ответа:

```json
{}
```

## Получение информации о типе региона

Метод: **GET**

Путь: **/region/types/{typeId}**

#### Запрос

Принимает запрос без тела.

#### Ответ

Возвращает информацию о типе региона в формате JSON:

- **id**: Идентификатор типа региона.
- **type**: Тип региона.

#### Статусы

- **200**: Запрос успешно выполнен и информация о типе региона получена.
- **400**: Если тип региона не указан (`typeId = null, typeId <= 0`).
- **401**: Неверные авторизационные данные.
- **404**: Тип региона с указанным идентификатором не найден.

Пример запроса:

```http
GET /region/types/{123} HTTP/1.1
```

Пример ответа:

```json
{
  "id": 123,
  "type": "Название типа региона"
}
```

## Добавление типа региона

Метод: **POST**

Путь: **/region/types**

#### Запрос

Принимает JSON-объект с полем:

- **type** (обязательно): Тип региона.

#### Ответ

Возвращает информацию о добавленном типе региона в формате JSON:

- **id**: Идентификатор добавленного типа региона.
- **type**: Тип региона.

* Если тип региона не указан, возвращается `None` в поле `type`.

#### Статусы

- **201**: Запрос успешно выполнен и тип региона добавлен.
- **400**: Отсутствует или пусто поле "type" в теле запроса.
- **401**: Неверные авторизационные данные.
- **409**: Тип региона с указанным именем уже существует.

Пример запроса:

```http
POST /region/types HTTP/1.1
Content-Type: application/json

{
  "type": "Название типа региона"
}
```

Пример ответа:

```json
{
  "id": 123,
  "type": "Название типа региона"
}
```

## Изменение типа региона

Метод: **PUT**

Путь: **/region/types/{typeId}**

#### Запрос

Принимает JSON-объект с полем:

- **type** (обязательно): Новый тип региона.

#### Ответ

Возвращает информацию об измененном типе региона в формате JSON:

- **id**: Идентификатор измененного типа региона.
- **type**: Новый тип региона.

#### Статусы

- **200**: Запрос успешно выполнен и тип региона изменен.
- **400**: Идентификатор типа региона некорректный (`typeId <= 0`) или отсутствует поле "type" в теле запроса.
- **401**: Неверные авторизационные данные.
- **404**: Тип региона с указанным идентификатором не найден.
- **409**: Тип региона с указанным именем уже существует.

Пример запроса:

```http
PUT /region/types/{123} HTTP/1.1
Content-Type: application/json

{
  "type": "Новый тип региона"
}
```

Пример ответа:

```json
{
  "id": 123,
  "type": "Новый тип региона"
}
```

## Удаление типа региона

Метод: **DELETE**

Путь: **/region/types/{typeId}**

#### Запрос

Отправляет пустое тело запроса.

#### Ответ

Отправляет пустое тело ответа.

#### Статусы

- **200**: Запрос успешно выполнен и тип региона удален.
- **400**: Идентификатор типа региона некорректный (`typeId <= 0`) или есть регионы с этим типом.
- **401**: Неверные авторизационные данные.
- **404**: Тип региона с указанным идентификатором не найден.

Пример запроса:

```http
DELETE /region/types/{123} HTTP/1.1
```

Пример ответа:

```json
{}
```

## Получение информации о погоде в регионе

Метод: **GET**

Путь: **/region/weather/{regionld}**

#### Запрос

Отправляет пустое тело запроса.

#### Ответ

Возвращает информацию о погоде в указанном регионе в формате JSON:

- **id**: Идентификатор региона.
- **regionName**: Название региона.
- **temperature**: Температура в регионе, °C.
- **humidity**: Влажность воздуха в регионе, %.
- **windSpeed**: Скорость ветра, м/с.
- **weatherCondition**: Текущее состояние погоды. Возможные значения: "CLEAR", "CLOUDY", "RAIN", "SNOW", "FOG", "STORM".
- **precipitationAmount**: Количество осадков, мм.
- **measurementDateTime**: Дата и время измерения погодных условий в формате ISO-8601.
- **weatherForecast**: Массив идентификаторов объектов с прогнозом погоды на ближайшие дни.

#### Статусы

- **200**: Запрос успешно выполнен и информация о погоде в регионе получена.
- **400**: Идентификатор региона некорректный (`regionld <= 0`).
- **401**: Неверные авторизационные данные.
- **404**: Регион с указанным идентификатором не найден или прогноз погоды для данного региона не найден.

Пример запроса:

```http
GET /region/weather/{123} HTTP/1.1
```

Пример ответа:

```json
{
  "id": 123,
  "regionName": "Название региона",
  "temperature": 20.5,
  "humidity": 70.0,
  "windSpeed": 3.5,
  "weatherCondition": "CLOUDY",
  "precipitationAmount": 0.0,
  "measurementDateTime": "2024-04-14T12:30:00Z",
  "weatherForecast": [
    456,
    789
  ]
}
```

## Поиск информации о погоде в регионе

Метод: **GET**

Путь: *

*

/region/weather/search?startDateTime={startDateTime}&endDateTime={endDateTime}&regionId={regionId}&weatherCondition={weatherCondition}&from=0&size=10
**

#### Запрос

Отправляет пустое тело запроса.

#### Параметры запроса

- **startDateTime**: Дата и время начала периода для поиска погодных условий, в формате ISO-8601. Если null, не
  участвует в фильтрации.
- **endDateTime**: Дата и время конца периода для поиска погодных условий, в формате ISO-8601. Если null, не участвует в
  фильтрации.
- **regionId**: Идентификатор региона, для которого ищется информация о погоде. Если null, не участвует в фильтрации.
- **weatherCondition**: Состояние погоды. Возможные значения: "CLEAR", "CLOUDY", "RAIN", "SNOW", "FOG", "STORM". Если
  null, не участвует в фильтрации.
- **from**: Количество элементов, которое необходимо пропустить для формирования страницы с результатами (по умолчанию
  0).
- **size**: Количество элементов на странице (по умолчанию 10).

#### Ответ

Возвращает информацию о погоде в указанных параметрах в формате JSON:

- **id**: Идентификатор региона.
- **regionName**: Название региона.
- **temperature**: Температура в регионе, °C.
- **humidity**: Влажность воздуха в регионе, %.
- **windSpeed**: Скорость ветра, м/с.
- **weatherCondition**: Текущее состояние погоды. Возможные значения: "CLEAR", "CLOUDY", "RAIN", "SNOW", "FOG", "STORM".
- **precipitationAmount**: Количество осадков, мм.
- **measurementDateTime**: Дата и время измерения погодных условий в формате ISO-8601.
- **weatherForecast**: Массив идентификаторов объектов с прогнозом погоды на ближайшие дни.

#### Статусы

- **200**: Запрос успешно выполнен и информация о погоде в регионе получена.
- **400**: Некорректные параметры запроса (например, regionId <= 0).
- **401**: Неверные авторизационные данные.
- **404**: Регион с указанным идентификатором не найден или прогноз погоды для данного региона не найден.

Пример запроса:

```http
GET /region/weather/search?startDateTime=2024-04-14T00:00:00Z&endDateTime=2024-04-15T00:00:00Z&regionId=123&weatherCondition=CLOUDY&from=0&size=10 HTTP/1.1
```

Пример ответа:

```json
[
  {
    "id": 123,
    "regionName": "Название региона",
    "temperature": 20.5,
    "humidity": 70.0,
    "windSpeed": 3.5,
    "weatherCondition": "CLOUDY",
    "precipitationAmount": 0.0,
    "measurementDateTime": "2024-04-14T12:30:00Z",
    "weatherForecast": [
      456,
      789
    ]
  },
  {
    "id": 456,
    "regionName": "Другой регион",
    "temperature": 22.0,
    "humidity": 75.0,
    "windSpeed": 2.0,
    "weatherCondition": "CLOUDY",
    "precipitationAmount": 0.0,
    "measurementDateTime": "2024-04-14T12:30:00Z",
    "weatherForecast": [
      789,
      1011
    ]
  }
]
```

## Добавление записи о погоде в регионе

Метод: **POST**

Путь: **/region/weather**

#### Запрос

Принимает JSON-объект с полями:

- regionId (обязательный): Идентификатор региона
- temperature (обязательный): Температура в регионе, °C
- humidity (обязательный): Влажность воздуха в регионе, %
- windSpeed (обязательный): Скорость ветра, м/с
- weatherCondition (обязательный): Текущее состояние погоды: "CLEAR", "CLOUDY", "RAIN", "SNOW", "FOG", "STORM"
- precipitationAmount (обязательный): Количество осадков, мм
- measurementDateTime (обязательный): Дата и время измерения погодных условий в формате ISO-8601
- weatherForecast (опциональный): Массив идентификаторов объектов с прогнозом погоды на ближайшие дни

#### Ответ

- **id**: Уникальный идентификатор созданной записи о погоде в регионе
- **temperature**: Температура в регионе, °C
- **humidity**: Влажность воздуха в регионе, %
- **windSpeed**: Скорость ветра, м/с
- **weatherCondition**: Текущее состояние погоды: "CLEAR", "CLOUDY", "RAIN", "SNOW", "FOG", "STORM"
- **precipitationAmount**: Количество осадков, мм
- **measurementDateTime**: Дата и время измерения погодных условий в формате ISO-8601
- **weatherForecast**: Массив идентификаторов объектов с прогнозом погоды на ближайшие дни

#### Статусы

- **200**: Запрос успешно выполнен и запись о погоде в регионе добавлена.
- **400**: Один из следующих случаев:
    - Некорректный идентификатор региона (regionId <= 0).
    - Дата и время измерения погодных условий не в формате ISO-8601.
    - Температура или скорость ветра отрицательные.
    - Неверное состояние погоды.
    - Количество осадков отрицательное.
- **401**: Неверные авторизационные данные.
- **404**: Регион с указанным идентификатором не найден или прогноз погоды для данного региона не найден.

Пример запроса:

```http
POST /region/weather HTTP/1.1
Content-Type: application/json

{
  "regionId": 123,
  "temperature": 25.5,
  "humidity": 60.0,
  "windSpeed": 3.0,
  "weatherCondition": "CLEAR",
  "precipitationAmount": 0.0,
  "measurementDateTime": "2024-04-14T12:00:00Z",
  "weatherForecast": [456, 789]
}
```

Пример ответа:

```json
{
  "id": 987,
  "temperature": 25.5,
  "humidity": 60.0,
  "windSpeed": 3.0,
  "weatherCondition": "CLEAR",
  "precipitationAmount": 0.0,
  "measurementDateTime": "2024-04-14T12:00:00Z",
  "weatherForecast": [
    456,
    789
  ]
}
```

## Изменение погоды в регионе

Метод: **PUT**

Путь: **/region/weather/{regionId}**

#### Запрос

Принимает JSON-объект с полями:

- **regionId** (обязательный): Идентификатор региона
- **temperature** (обязательный): Температура в регионе, °C
- **humidity** (обязательный): Влажность воздуха в регионе, %
- **windSpeed** (обязательный): Скорость ветра, м/с
- **weatherCondition** (обязательный): Текущее состояние погоды: "CLEAR", "CLOUDY", "RAIN", "SNOW", "FOG", "STORM"
- **precipitationAmount** (обязательный): Количество осадков, мм
- **measurementDateTime** (обязательный): Дата и время измерения погодных условий в формате ISO-8601
- **weatherForecast** (опциональный): Массив идентификаторов объектов с прогнозом погоды на ближайшие дни

#### Ответ

Отправляет JSON-объект с полями:

- **id**: Уникальный идентификатор созданной записи о погоде в регионе
- **temperature**: Температура в регионе, °C
- **humidity**: Влажность воздуха в регионе, %
- **windSpeed**: Скорость ветра, м/с
- **weatherCondition**: Текущее состояние погоды: "CLEAR", "CLOUDY", "RAIN", "SNOW", "FOG", "STORM"
- **precipitationAmount**: Количество осадков, мм
- **measurementDateTime**: Дата и время измерения погодных условий в формате ISO-8601
- **weatherForecast**: Массив идентификаторов объектов с прогнозом погоды на ближайшие дни

#### Пример запроса

```json
{
  "regionId": 123,
  "temperature": 25.5,
  "humidity": 60.2,
  "windSpeed": 3.4,
  "weatherCondition": "CLEAR",
  "precipitationAmount": 0,
  "measurementDateTime": "2024-04-15T08:00:00Z",
  "weatherForecast": [
    456,
    789
  ]
}
```

Пример ответа:

```json
{
  "id": 987,
  "temperature": 25.5,
  "humidity": 60.2,
  "windSpeed": 3.4,
  "weatherCondition": "CLEAR",
  "precipitationAmount": 0,
  "measurementDateTime": "2024-04-15T08:00:00Z",
  "weatherForecast": [
    456,
    789
  ]
}
```

## Удаление погоды для региона

Метод: **DELETE**

Путь: **/region/weather/{regionId}**

#### Запрос

Отправляет пустое тело запроса.

#### Ответ

Отправляет пустое тело ответа.

#### Статусы

- **200**: Запрос успешно выполнен, и погода для указанного региона удалена.
- **400**: Один из следующих случаев:
    - Идентификатор региона некорректный (`regionId <= 0`).
- **401**: Неверные авторизационные данные.
- **404**: Регион с указанным идентификатором не найден.

Пример запроса:

```http
DELETE /region/weather/{123} HTTP/1.1
```

Пример ответа:

```json
{}
```

## Добавление погоды для конкретного региона

Метод: **POST**

Путь: **/region/{regionId}/weather/{weatherId}**

#### Запрос

Отправляет пустое тело запроса.

#### Ответ

Отправляет JSON-объект с полями:

- id (long): Подтверждение уникального идентификатора региона
- regionId (long): Идентификатор региона
- regionName (string): Новое название региона
- temperature (float): Новая температура в регионе, °C
- humidity (float): Новая влажность воздуха в регионе, %
- windSpeed (float): На Скорость ветра, м/с
- weatherCondition (string): Текущее состояние погоды, доступные значения: "CLEAR", "CLOUDY", "RAIN", "SNOW", "FOG", "
  STORM"
- precipitationAmount (float): Количество осадков, мм
- measurementDateTime (dateTime): Дата и время измерения погодных условий в формате ISO-8601
- weatherForecast (array): Массив идентификаторов объектов с прогнозом погоды на ближайшие дни

#### Статусы

- **200**: Запрос успешно выполнен.
- **400**: Один из следующих случаев:
    - Идентификатор региона некорректный (`regionId <= 0`).
    - Идентификатор погоды некорректный (`weatherId <= 0`).
- **401**: Неверные авторизационные данные.
- **404**: Регион с указанным идентификатором не найден, или погода для указанного региона и идентификатора не найдена.

Пример запроса:

```http
POST /region/123/weather/456 HTTP/1.1
```

Пример ответа:

```json
{
  "id": 123,
  "regionId": 123,
  "regionName": "Название региона",
  "temperature": 25.0,
  "humidity": 50.0,
  "windSpeed": 10.0,
  "weatherCondition": "CLEAR",
  "precipitationAmount": 0.0,
  "measurementDateTime": "2024-04-16T12:00:00Z",
  "weatherForecast": [
    789,
    790
  ]
}
```

## Удаление погоды для региона

Метод: **DELETE**

Путь: **/region/{regionId}/weather/{weatherId}**

#### Запрос

Отправляет пустое тело запроса.

#### Ответ

Отправляет JSON-объект с полями:

- id (long): Идентификатор региона
- name (string): Название региона
- parentRegion (string): Название родительского региона
- latitude (double): Координаты широты
- longitude (double): Координаты долготы

#### Статусы

- **200**: Запрос успешно выполнен.
- **400**: Один из следующих случаев:
    - Идентификатор региона некорректный (`regionId <= 0`).
    - Идентификатор погоды некорректный (`weatherId <= 0`).
- **401**: Неверные авторизационные данные.
- **404**: Регион с указанным идентификатором не найден.

Пример запроса:

```http
DELETE /region/123/weather/456 HTTP/1.1
```

Пример ответа:

```json
{
  "id": 123,
  "name": "Название региона",
  "parentRegion": "Название родительского региона",
  "latitude": 50.0,
  "longitude": 30.0
}
```

## Получение информации о прогнозе погоды

Метод: **GET**

Путь: **/region/weather/forecast/{forecastId}**

#### Запрос

Отправляет пустое тело запроса.

#### Ответ

Отправляет JSON-объект с полями:

- id (long): Уникальный идентификатор прогноза погоды
- dateTime (dateTime): Дата и время прогноза в формате ISO-8601
- temperature (float): Прогнозируемая температура, °C
- weatherCondition (string): Текущее состояние погоды. Допустимые значения: "CLEAR", "CLOUDY", "RAIN", "SNOW", "FOG", "
  STORM"
- regionId (long): Идентификатор региона, для которого сделан прогноз

#### Статусы

- **200**: Запрос успешно выполнен.
- **400**: Один из следующих случаев:
    - Идентификатор прогноза погоды не указан (`forecastId = null`).
    - Дата и время прогноза не в формате ISO-8601.
    - Состояние погоды не валидно.
    - Идентификатор прогноза погоды меньше или равен нулю (`forecastId <= 0`).
- **401**: Неверные авторизационные данные.
- **404**: Прогноза погоды с указанным идентификатором не существует.

Пример запроса:

```http
GET /region/weather/forecast/{forecastId} HTTP/1.1
```

Пример ответа:

```json
{
  "id": 123,
  "dateTime": "2024-04-15T12:00:00Z",
  "temperature": 20.5,
  "weatherCondition": "CLEAR",
  "regionId": 456
}
```

## Изменение прогноза погоды

Метод: **PUT**

Путь: **/region/weather/forecast/{forecastId}**

#### Запрос

Отправляет JSON-объект с полями:

- temperature (float): Новая прогнозируемая температура, °C
- weatherCondition (string): Новое прогнозируемое состояние погоды. Допустимые значения: "CLEAR", "CLOUDY", "RAIN", "
  SNOW", "FOG", "STORM"
- dateTime (dateTime): Новая дата и время прогноза в формате ISO-8601

#### Ответ

Отправляет JSON-объект с полями:

- id (long): Подтверждение уникального идентификатора прогноза погоды
- dateTime (dateTime): Новая дата и время прогноза в формате ISO-8601
- temperature (float): Новая температура, °C
- weatherCondition (string): Новое состояние погоды
- regionId (long): Идентификатор региона

#### Статусы

- **200**: Запрос успешно выполнен.
- **400**: Один из следующих случаев:
    - Идентификатор прогноза погоды не указан (`forecastId = null`).
    - Дата и время прогноза не в формате ISO-8601.
    - Состояние погоды не валидно.
    - Идентификатор прогноза погоды меньше или равен нулю (`forecastId <= 0`).
- **401**: Неверные авторизационные данные.
- **404**: Прогноза погоды с указанным идентификатором не существует.

Пример запроса:

```http
PUT /region/weather/forecast/{forecastId} HTTP/1.1
Content-Type: application/json

{
  "temperature": 25.5,
  "weatherCondition": "CLEAR",
  "dateTime": "2024-04-16T12:00:00Z"
}
```

Пример ответа:

```json
{
  "id": 123,
  "dateTime": "2024-04-16T12:00:00Z",
  "temperature": 25.5,
  "weatherCondition": "CLEAR",
  "regionId": 456
}
```

## Добавление прогноза погоды

Метод: **POST**

Путь: **/region/weather/forecast/**

#### Запрос

Отправляет JSON-объект с полями:

- regionId (long): Идентификатор региона, для которого делается прогноз
- dateTime (dateTime): Дата и время, на которые делается прогноз в формате ISO-8601
- temperature (float): Прогнозируемая температура, °C
- weatherCondition (string): Прогнозируемое состояние погоды. Допустимые значения: "CLEAR", "CLOUDY", "RAIN", "SNOW", "
  FOG", "STORM"

#### Ответ

Отправляет JSON-объект с полями:

- id (long): Уникальный идентификатор созданного прогноза погоды
- regionId (long): Идентификатор региона, для которого был создан прогноз
- temperature (float): Прогнозируемая температура, °C
- weatherCondition (string): Прогнозируемое состояние погоды
- dateTime (dateTime): Дата и время прогноза в формате ISO-8601
- precipitationAmount (float): Количество осадков, мм
- windSpeed (float): Скорость ветра, м/c

#### Статусы

- **200**: Запрос успешно выполнен.
- **400**: Один из следующих случаев:
    - Идентификатор региона не указан (`regionId = null`).
    - Дата и время прогноза не в формате ISO-8601.
    - Состояние погоды не валидно.
    - Идентификатор региона меньше или равен нулю (`regionId <= 0`).
- **401**: Неверные авторизационные данные.
- **404**: Региона с указанным идентификатором не существует.

Пример запроса:

```http
POST /region/weather/forecast/ HTTP/1.1
Content-Type: application/json

{
  "regionId": 123,
  "dateTime": "2024-04-16T12:00:00Z",
  "temperature": 25.5,
  "weatherCondition": "CLEAR"
}
```

Пример ответа:

```json
{
  "id": 456,
  "regionId": 123,
  "temperature": 25.5,
  "weatherCondition": "CLEAR",
  "dateTime": "2024-04-16T12:00:00Z",
  "precipitationAmount": 10.2,
  "windSpeed": 3.4
}
```

## Удаление прогноза погоды

Метод: **DELETE**

Путь: **/region/weather/forecast/{forecastId}**

#### Запрос

Отправляет пустое тело запроса.

#### Ответ

Отправляет пустое тело ответа.

#### Статусы

- **200**: Запрос успешно выполнен, и прогноз погоды удален.
- **400**: Один из следующих случаев:
    - Идентификатор прогноза погоды некорректный (`forecastId <= 0`).
- **401**: Неверные авторизационные данные.
- **404**: Прогноз погоды с указанным идентификатором не найден.

Пример запроса:

```http
DELETE /region/weather/forecast/123 HTTP/1.1
```

Пример ответа:

```http
HTTP/1.1 200 OK
```